"""
LangGraph Supervisor 模块
实现基于 LangGraph 的 Supervisor 工作流，支持记忆管理和多智能体协调
"""

from typing import Any, List, Annotated, Dict
import operator
import asyncio
from langchain_core.messages import HumanMessage, AIMessage, BaseMessage
from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI
from langgraph.graph import StateGraph, END
from langgraph.checkpoint.memory import MemorySaver
import logging

logger = logging.getLogger(__name__)

# 导入查询重写功能
try:
    from enhanced_memory.query_rewriter import QueryRewriter, QueryRewriteResult
    QUERY_REWRITER_AVAILABLE = True
except ImportError:
    logger.warning("Query rewriter not available, using basic routing")
    QUERY_REWRITER_AVAILABLE = False

# 查询重写缓存（与text2sql智能体相同的性能优化）
_query_rewriter_cache = {}
_query_rewrite_results_cache = {}

# 🔧 修复：添加执行计数器防止重复执行
_execution_counter = {}
_max_execution_per_query = 1  # 每个查询最多执行一次

# 🔧 修复：添加记忆管理器缓存，避免重复初始化
_memory_manager_cache = {}
_config_manager_cache = {}

async def intelligent_route_query_with_rewrite(user_input: str, user_id: str = None, session_id: str = None) -> Dict[str, Any]:
    """
    🚀 统一查询重写和智能路由函数
    系统唯一的查询重写入口点，避免重复实现

    功能：
    1. 执行查询重写（代词消解、省略补全、时间引用）
    2. 基于重写后的查询进行智能路由决策
    3. 将重写信息传递给目标智能体

    Args:
        user_input: 用户输入的查询内容
        user_id: 用户ID
        session_id: 会话ID

    Returns:
        Dict: 包含路由目标和重写信息的字典
    """
    try:
        # 🔧 修复：防止重复执行
        execution_key = f"{user_input}_{user_id}_{session_id}_{hash(user_input)}"
        if execution_key in _execution_counter:
            _execution_counter[execution_key] += 1
            if _execution_counter[execution_key] > _max_execution_per_query:
                logger.warning(f"🚫 防止重复执行: '{user_input}' (第{_execution_counter[execution_key]}次)")
                # 返回缓存的结果或默认路由
                return {
                    "route_target": "general",
                    "original_query": user_input,
                    "rewritten_query": user_input,
                    "rewrite_confidence": 0.0,
                    "rewrite_applied": False,
                    "query_used_for_routing": user_input,
                    "confidence_threshold": 0.7,
                    "conversation_history": [],
                    "reference_type": "duplicate_execution",
                    "resolved_entities": [],
                    "context_used": []
                }
        else:
            _execution_counter[execution_key] = 1
        # 1. 获取对话历史用于查询重写
        conversation_history = []
        if user_id and session_id:
            conversation_history = await _get_conversation_history(user_id, session_id)

        # 2. 执行查询重写（系统唯一入口点）
        rewrite_result = await _perform_query_rewrite(user_input, conversation_history, user_id, session_id)

        # 3. 智能路由决策：根据查询类型和置信度选择最佳查询
        # 🔧 修复：优化置信度阈值和路由逻辑

        # 对于不同类型的查询使用不同的置信度阈值
        confidence_threshold = 0.7  # 默认阈值

        # 省略查询和代词查询使用较低的阈值
        if rewrite_result.reference_type in ["ellipsis", "pronoun", "context"]:
            confidence_threshold = 0.4  # 省略查询阈值降低
        elif rewrite_result.reference_type == "temporal":
            confidence_threshold = 0.5  # 时间引用阈值适中

        # 决定使用哪个查询进行路由
        use_rewritten = rewrite_result.confidence > confidence_threshold
        query_for_routing = rewrite_result.rewritten_query if use_rewritten else user_input

        # 执行路由决策
        route_target = intelligent_route_query(query_for_routing)

        # 🔧 修复：避免重复路由调用，优化智能路由逻辑
        if route_target == "general" and not use_rewritten and rewrite_result.confidence > 0.3:
            # 只有当重写后查询明显不同时才尝试重新路由
            if rewrite_result.rewritten_query != user_input and len(rewrite_result.rewritten_query) > len(user_input) * 1.5:
                alternative_route = intelligent_route_query(rewrite_result.rewritten_query)
                if alternative_route != "general":
                    logger.info(f"🔄 [智能路由优化] 原查询路由到general，使用重写后查询: '{rewrite_result.rewritten_query}' -> {alternative_route}")
                    route_target = alternative_route
                    query_for_routing = rewrite_result.rewritten_query
                    use_rewritten = True
                else:
                    logger.debug(f"🔄 [智能路由优化] 重写后查询仍路由到general，保持原路由")

        # 记录查询重写和路由决策
        if use_rewritten:
            logger.info(f"🔄 [统一查询重写] '{user_input}' -> '{rewrite_result.rewritten_query}' (confidence: {rewrite_result.confidence:.2f}, threshold: {confidence_threshold})")
            logger.info(f"🎯 [路由决策] 使用重写后查询: '{query_for_routing}' -> {route_target}")
        else:
            logger.debug(f"🔄 [统一查询重写] 置信度不足: '{user_input}' (confidence: {rewrite_result.confidence:.2f}, threshold: {confidence_threshold})")
            logger.info(f"🎯 [路由决策] 使用原始查询: '{query_for_routing}' -> {route_target}")

        return {
            "route_target": route_target,
            "original_query": user_input,
            "rewritten_query": rewrite_result.rewritten_query,
            "rewrite_confidence": rewrite_result.confidence,
            "rewrite_applied": use_rewritten,  # 🔧 修复：使用实际的重写应用状态
            "query_used_for_routing": query_for_routing,  # 新增：实际用于路由的查询
            "confidence_threshold": confidence_threshold,  # 新增：使用的置信度阈值
            "conversation_history": conversation_history,
            # 与text2sql智能体相同的详细重写信息
            "reference_type": rewrite_result.reference_type,
            "resolved_entities": rewrite_result.resolved_entities,
            "context_used": rewrite_result.context_used
        }

    except Exception as e:
        logger.error(f"Error in intelligent routing with rewrite: {e}")
        # 降级到基础路由
        return {
            "route_target": intelligent_route_query(user_input),
            "original_query": user_input,
            "rewritten_query": user_input,
            "rewrite_confidence": 0.0,
            "rewrite_applied": False,
            "conversation_history": []
        }

def intelligent_route_query(user_input: str) -> str:
    """
    🚀 优化的智能路由函数
    优先使用轻量级规则匹配，复杂查询才使用LLM路由

    Args:
        user_input: 用户输入的查询内容

    Returns:
        str: 路由目标 ('text2sql_agent', 'dingtalk_agent', 'supervisor', 或 'general')
    """
    try:
        # 🎯 步骤1：使用轻量级分类器进行快速路由
        from optimization_solution import get_optimized_supervisor

        supervisor = get_optimized_supervisor()
        classification = supervisor.route_request(user_input)

        # 如果是简单操作，直接返回路由结果
        if classification["optimization_applied"]:
            route_result = classification["agent_type"]
            logger.info(f"⚡ 轻量级路由成功: '{user_input}' -> {route_result}")
            return route_result

        # 🎯 步骤1.5：知识类查询检测（在LLM路由之前）
        knowledge_keywords = [
            "文档", "知识库", "指南", "流程", "政策", "规范", "FAQ", "是什么", "如何", "怎么",
            "说明", "手册", "教程", "报错", "解决方案", "使用方法", "接入", "配置", "参数解释",
            "报销", "请假", "考勤", "打卡", "API", "鉴权", "限流", "错误码", "环境变量",
            "常见问题", "问题解答", "操作指南", "使用指南", "功能说明"
        ]

        # 检查是否包含知识类关键词
        user_input_lower = user_input.lower()
        knowledge_score = sum(1 for keyword in knowledge_keywords if keyword in user_input_lower)

        # 排除明显的操作类和SQL类查询
        operation_keywords = ["创建", "添加", "安排", "删除", "修改", "设置"]
        sql_keywords = ["第二多", "最多", "排名", "统计", "查询", "数量", "总数", "平均"]

        has_operation = any(keyword in user_input_lower for keyword in operation_keywords)
        has_sql = any(keyword in user_input_lower for keyword in sql_keywords)

        # 如果知识类关键词较多且不是操作或SQL查询，路由到knowledge_agent
        if knowledge_score >= 1 and not has_operation and not has_sql:
            logger.info(f"📚 知识类关键词检测: '{user_input}' -> knowledge_agent (score: {knowledge_score})")
            return "knowledge_agent"

        # 🎯 步骤2：复杂查询使用LLM路由
        logger.info(f"🤖 使用LLM路由处理复杂查询: '{user_input}'")

        # 创建智能语义路由的prompt
        routing_prompt = ChatPromptTemplate.from_messages([
            ("system", """你是一个高级智能路由分析器，需要通过深度语义理解来分析用户查询的真实意图，并决定路由到最合适的智能体。

系统架构：
🎬 text2sql_agent - 电影数据库查询和数据分析专家
🔧 dingtalk_agent - 钉钉办公功能专家
👋 supervisor - 问候、介绍和通用回复处理
🌐 general - 与现有功能无关的查询

语义路由判断标准：

【路由到 supervisor】：
- 问候语：你好、hello、hi、您好等各种形式的打招呼
- 功能询问：询问能力、功能介绍、帮助信息
- 系统介绍：想了解系统能做什么

【路由到 dingtalk_agent】：
- 办公管理语义：
  * 任务管理：创建/查看/完成任务、待办事项、工作安排
  * 日程管理：查看/安排日程、会议安排、时间管理
  * 联系人管理：搜索同事、查找联系人、通讯录
  * 钉钉功能：明确提到钉钉相关的任何功能
- 关键语义特征：
  * 包含"创建"+"任务/待办/事项"的组合
  * 包含"查看"+"日程/安排/会议"的组合
  * 包含"搜索/查找"+"同事/联系人"的组合
  * 明确提到"钉钉"相关词汇

【路由到 text2sql_agent】：
- 数据查询语义：
  * 电影相关：影片信息、演员资料、票房数据、电影推荐
  * 数据分析：统计、查询、搜索、信息检索、数据分析
  * 客户信息：客户查询、记录查询、业务数据
- 关键语义特征：
  * 包含查询、搜索、统计等数据操作词汇
  * 涉及电影、演员、票房等娱乐内容
  * 需要数据库查询的任何请求

【路由到 general】：
- 与上述功能完全无关的查询：
  * 天气、新闻、百科知识
  * 闲聊、情感交流
  * 技术问题、编程帮助
  * 其他生活常识或专业领域问题

路由决策原则：
1. 优先识别明确的功能意图
2. 对于模糊查询，根据语义相似度判断
3. 如果完全无关，路由到 general
4. 如果不确定但可能相关，优先路由到 text2sql_agent

请仔细分析用户查询的语义内容，返回最合适的路由目标：'supervisor', 'dingtalk_agent', 'text2sql_agent', 或 'general'"""),
            ("human", "用户查询：{query}")
        ])

        # 初始化模型
        model = ChatOpenAI(
            model="gpt-4o-mini",
            temperature=0.1,  # 稍微提高温度以获得更好的语义理解
            max_tokens=100
        )

        # 创建路由链
        routing_chain = routing_prompt | model

        # 执行路由判断
        response = routing_chain.invoke({"query": user_input})
        route_decision = response.content.strip().lower()

        # 标准化路由决策
        final_route = None
        if 'supervisor' in route_decision:
            final_route = 'supervisor'
        elif 'dingtalk_agent' in route_decision or 'dingtalk' in route_decision:
            final_route = 'dingtalk_agent'
        elif 'text2sql_agent' in route_decision or 'text2sql' in route_decision:
            final_route = 'text2sql_agent'
        elif 'knowledge_agent' in route_decision or 'knowledge' in route_decision:
            final_route = 'knowledge_agent'
        elif 'general' in route_decision:
            final_route = 'general'

        if final_route:
            logger.info(f"语义路由决策: '{user_input}' -> {final_route}")
            return final_route
        else:
            # 如果返回格式不标准，尝试解析
            if any(word in route_decision for word in ['钉钉', 'dingtalk', '办公', '任务', '日程', '会议']):
                logger.info(f"语义路由决策(解析): '{user_input}' -> dingtalk_agent")
                return 'dingtalk_agent'
            elif any(word in route_decision for word in ['电影', 'sql', '数据', '查询', '统计']):
                logger.info(f"语义路由决策(解析): '{user_input}' -> text2sql_agent")
                return 'text2sql_agent'
            elif any(word in route_decision for word in ['知识', 'knowledge', '文档', '政策', '流程', 'FAQ', '指南']):
                logger.info(f"语义路由决策(解析): '{user_input}' -> knowledge_agent")
                return 'knowledge_agent'
            elif any(word in route_decision for word in ['你好', 'hello', '功能', '帮助']):
                logger.info(f"语义路由决策(解析): '{user_input}' -> supervisor")
                return 'supervisor'
            else:
                logger.warning(f"路由决策无法解析: {route_decision}, 使用通用回复")
                return 'general'

    except Exception as e:
        logger.error(f"智能语义路由失败: {e}, 使用通用回复")
        return 'general'

async def _get_conversation_history(user_id: str, session_id: str) -> List[Dict[str, str]]:
    """
    获取对话历史用于查询重写
    与text2sql智能体中的上下文处理方式保持一致
    """
    try:
        # 🔧 修复：使用缓存的记忆管理器，避免重复初始化
        cache_key = f"{user_id}_{session_id}" if user_id and session_id else "default"

        if cache_key not in _memory_manager_cache:
            from dingding.memory_manager import MemoryManager
            from dingding.config_manager import ConfigManager

            # 缓存配置管理器
            if "default" not in _config_manager_cache:
                _config_manager_cache["default"] = ConfigManager()
                logger.info("配置管理器初始化完成")

            config = _config_manager_cache["default"]
            _memory_manager_cache[cache_key] = MemoryManager(config)
            logger.info(f"记忆管理器初始化完成，缓存键: {cache_key}")

        memory_manager = _memory_manager_cache[cache_key]

        # 获取记忆上下文（使用默认参数）
        max_messages = 2  # 默认最大对话历史数
        memory_context = memory_manager.get_memory_context(session_id, max_messages=max_messages)

        # 解析记忆上下文为对话历史格式（与text2sql智能体相同的解析逻辑）
        conversation_history = []
        if memory_context:
            # 使用与enhanced_memory相同的解析方式
            parts = memory_context.split(" | ")
            for part in parts:
                part = part.strip()
                if "用户:" in part:
                    content = part.replace("用户:", "").strip()
                    if content:  # 确保内容不为空
                        conversation_history.append({
                            "role": "user",
                            "content": content
                        })
                elif "助手:" in part:
                    content = part.replace("助手:", "").strip()
                    if content:  # 确保内容不为空
                        conversation_history.append({
                            "role": "assistant",
                            "content": content
                        })

        # 返回最近的对话历史（与text2sql智能体相同的限制）
        return conversation_history[-max_messages:]

    except Exception as e:
        logger.warning(f"Failed to get conversation history: {e}")
        return []

async def _perform_query_rewrite(user_input: str, conversation_history: List[Dict[str, str]], user_id: str = None, session_id: str = None):
    """
    执行查询重写 - 系统唯一的查询重写实现

    功能：
    - 代词消解：处理"它"、"这个"、"那个"等代词引用
    - 省略补全：处理"那第二多的呢？"等省略查询
    - 时间引用：处理"刚才"、"之前"等时间表达
    - 上下文理解：基于对话历史理解查询意图

    注意：这是系统中唯一的查询重写入口点，其他组件不应重复实现
    """
    try:
        # 与text2sql智能体相同的输入验证
        safe_user_input = user_input if user_input is not None else ""

        # 与text2sql智能体相同的可用性检查
        if not QUERY_REWRITER_AVAILABLE:
            logger.warning("Query rewriter not available, using original query")
            from enhanced_memory.query_rewriter import QueryRewriteResult
            return QueryRewriteResult(
                original_query=safe_user_input,
                rewritten_query=safe_user_input,
                confidence=0.0,
                reference_type="none",
                resolved_entities=[],
                context_used=[]
            )

        # 🔧 修复：即使没有对话历史，也要检查是否需要重写
        # 创建查询重写器进行需要性检查
        cache_key = f"{user_id}_{session_id}" if user_id else "default"
        if cache_key not in _query_rewriter_cache:
            _query_rewriter_cache[cache_key] = QueryRewriter()
        query_rewriter = _query_rewriter_cache[cache_key]

        # 检查是否需要重写（即使没有对话历史）
        if not conversation_history:
            if not query_rewriter._needs_rewriting(safe_user_input):
                logger.debug("No conversation history and no rewriting needed")
                from enhanced_memory.query_rewriter import QueryRewriteResult
                return QueryRewriteResult(
                    original_query=safe_user_input,
                    rewritten_query=safe_user_input,
                    confidence=1.0,  # 无需重写时置信度为1.0
                    reference_type="none",
                    resolved_entities=[],
                    context_used=[]
                )
            else:
                # 需要重写但没有对话历史，提供友好提示
                logger.warning(f"Query '{safe_user_input}' needs rewriting but no conversation history available")
                from enhanced_memory.query_rewriter import QueryRewriteResult
                return QueryRewriteResult(
                    original_query=safe_user_input,
                    rewritten_query=f"抱歉，您的查询「{safe_user_input}」似乎需要参考之前的对话内容，但我没有找到相关的对话历史。请提供更完整的查询信息。",
                    confidence=0.8,  # 提示性重写的置信度
                    reference_type="ellipsis_without_context",
                    resolved_entities=[],
                    context_used=[]
                )

        # 使用已创建的查询重写器（避免重复创建）

        # 检查查询重写结果缓存（与text2sql智能体相同的性能优化）
        result_cache_key = f"{user_input}_{hash(str(conversation_history))}"
        if result_cache_key in _query_rewrite_results_cache:
            logger.debug(f"Using cached query rewrite result for: {user_input}")
            return _query_rewrite_results_cache[result_cache_key]

        # 执行查询重写（与text2sql智能体相同的调用方式）
        rewrite_result = await query_rewriter.rewrite_query(
            user_input, conversation_history, user_id
        )

        # 缓存结果（与text2sql智能体相同的缓存策略）
        _query_rewrite_results_cache[result_cache_key] = rewrite_result

        # 与text2sql智能体相同的日志记录
        logger.info(f"Query rewrite: '{user_input}' -> '{rewrite_result.rewritten_query}' (confidence: {rewrite_result.confidence})")

        return rewrite_result

    except Exception as e:
        logger.error(f"Failed to perform query rewrite: {e}")
        # 与text2sql智能体相同的降级方案，确保输入有效性
        from enhanced_memory.query_rewriter import QueryRewriteResult

        # 确保输入不为None
        safe_user_input = user_input if user_input is not None else ""

        return QueryRewriteResult(
            original_query=safe_user_input,
            rewritten_query=safe_user_input,
            confidence=0.0,
            reference_type="error",
            resolved_entities=[],
            context_used=[]
        )

# 定义状态类型
class SupervisorState(dict):
    """Supervisor 状态类型"""
    messages: Annotated[List[BaseMessage], operator.add]
    next: str
    user_id: str = "default"
    session_id: str = "default"

def create_supervisor(agents: List[Any], **kwargs) -> StateGraph:
    """
    创建统一的 Supervisor 工作流

    Args:
        agents: 所有智能体列表，包括 text2sql_agent、dingtalk_agent 和 knowledge_agent
        **kwargs: 其他参数（保持向后兼容）
            - model: 语言模型（已内置，可选）
            - prompt: Supervisor 提示词（已内置，可选）
            - dingtalk_agent: 钉钉智能体（向后兼容，会被添加到agents中）

    Returns:
        编译后的工作流
    """
    try:
        # 处理向后兼容的参数
        dingtalk_agent = kwargs.get('dingtalk_agent', None)
        knowledge_agent = kwargs.get('knowledge_agent', None)

        # 统一管理所有智能体
        all_agents = list(agents) if agents else []
        if dingtalk_agent and dingtalk_agent not in all_agents:
            all_agents.append(dingtalk_agent)
        if knowledge_agent and knowledge_agent not in all_agents:
            all_agents.append(knowledge_agent)

        logger.info(f"Creating unified supervisor with {len(all_agents)} agents")

        # 创建状态图
        workflow = StateGraph(SupervisorState)
        
        # 创建增强的 Supervisor 节点
        async def supervisor_node(state: SupervisorState) -> SupervisorState:
            """增强的Supervisor决策节点，支持查询重写和智能语义路由"""
            try:
                messages = state.get("messages", [])
                if not messages:
                    return {"next": "FINISH"}

                # 获取最后一条用户消息
                last_message = messages[-1]
                user_input = last_message.content if hasattr(last_message, 'content') else str(last_message)

                # 获取用户ID和会话ID
                user_id = state.get("user_id", "default")
                session_id = state.get("session_id", f"user_{user_id}")

                # 🚀 执行查询重写和智能路由
                routing_result = await intelligent_route_query_with_rewrite(user_input, user_id, session_id)

                route_decision = routing_result["route_target"]
                rewrite_applied = routing_result["rewrite_applied"]

                # 如果查询被重写，更新消息（与text2sql智能体相同的处理逻辑）
                if rewrite_applied:
                    rewritten_query = routing_result["rewritten_query"]
                    rewrite_confidence = routing_result["rewrite_confidence"]

                    # 与text2sql智能体相同的日志记录
                    logger.info(f"🔄 Query rewritten: '{user_input}' -> '{rewritten_query}' (confidence: {rewrite_confidence:.2f})")

                    # 添加重写信息到状态（与text2sql智能体相同的状态管理）
                    state["original_query"] = user_input
                    state["rewritten_query"] = rewritten_query
                    state["rewrite_confidence"] = rewrite_confidence
                    state["rewrite_info"] = {
                        "confidence": rewrite_confidence,
                        "reference_type": routing_result.get("reference_type", "unknown"),
                        "resolved_entities": routing_result.get("resolved_entities", []),
                        "context_used": routing_result.get("context_used", [])
                    }

                    # 更新最后一条消息为重写后的查询（与text2sql智能体相同的消息更新方式）
                    if isinstance(last_message, HumanMessage):
                        messages[-1] = HumanMessage(content=rewritten_query)
                        state["messages"] = messages

                # 获取详细的分类信息
                from optimization_solution import get_optimized_supervisor
                supervisor = get_optimized_supervisor()
                classification = supervisor.route_request(user_input)

                logger.info(f"Supervisor semantic routing to: {route_decision}")

                # 将分类信息添加到状态中，供后续节点使用
                state["operation_type"] = classification.get("operation_type", "unknown")
                state["agent_type"] = classification.get("agent_type", route_decision)
                state["requires_memory"] = classification.get("requires_memory", True)
                state["optimization_applied"] = classification.get("optimization_applied", False)

                # 根据路由决策处理
                if route_decision == 'supervisor':
                    # 问候和功能介绍回复
                    response_content = """你好！我是您的智能助手，集成了电影数据库查询、钉钉办公和企业知识检索功能。

🎬 **电影数据库服务**：查找影片信息和数据分析
🔧 **钉钉办公服务**：任务管理和日程安排
📚 **企业知识检索**：公司政策、技术文档、FAQ查询

请问您需要什么帮助？"""

                    # 返回supervisor的直接回复
                    supervisor_message = AIMessage(
                        content=response_content,
                        name="supervisor"
                    )

                    return {
                        "messages": [supervisor_message],
                        "next": "FINISH"
                    }

                elif route_decision == 'general':
                    # 通用友好回复机制
                    response_content = """感谢您的提问！我是专门为电影数据库查询和钉钉办公功能设计的智能助手。

虽然我无法直接回答您当前的问题，但我可以帮您：

🎬 **电影相关查询**：
• 搜索电影信息和演员资料
• 分析票房数据和统计信息
• 推荐电影和数据查询

🔧 **钉钉办公功能**：
• 创建和管理待办事项
• 查看和安排日程会议
• 搜索联系人和同事信息

如果您有这些方面的需求，我很乐意为您提供帮助！"""

                    # 返回supervisor的直接回复
                    supervisor_message = AIMessage(
                        content=response_content,
                        name="supervisor"
                    )

                    return {
                        "messages": [supervisor_message],
                        "next": "FINISH"
                    }

                else:
                    # 路由到专业智能体，不返回中间消息
                    return {
                        "messages": [],
                        "next": route_decision
                    }

            except Exception as e:
                logger.error(f"Supervisor node error: {e}")
                # 错误时返回友好的通用回复
                error_message = AIMessage(
                    content="抱歉，我遇到了一些技术问题。请稍后重试，或者告诉我您需要什么帮助？",
                    name="supervisor"
                )
                return {
                    "messages": [error_message],
                    "next": "FINISH"
                }
        
        # 添加 Supervisor 节点（异步包装）
        def supervisor_node_sync(state: SupervisorState) -> SupervisorState:
            """同步包装的supervisor节点"""
            try:
                # 在同步环境中运行异步函数
                import asyncio
                try:
                    loop = asyncio.get_event_loop()
                    if loop.is_running():
                        # 如果事件循环正在运行，使用线程池
                        import concurrent.futures
                        with concurrent.futures.ThreadPoolExecutor() as executor:
                            future = executor.submit(asyncio.run, supervisor_node(state))
                            return future.result(timeout=30)
                    else:
                        return loop.run_until_complete(supervisor_node(state))
                except RuntimeError:
                    # 没有事件循环，创建新的
                    return asyncio.run(supervisor_node(state))
            except Exception as e:
                logger.error(f"Supervisor node error: {e}")
                # 🔧 修复：避免重复路由调用，直接返回通用错误回复
                error_message = AIMessage(
                    content="抱歉，我遇到了一些技术问题。请稍后重试，或者告诉我您需要什么帮助？",
                    name="supervisor"
                )
                return {
                    "messages": [error_message],
                    "next": "FINISH"
                }

        workflow.add_node("supervisor", supervisor_node_sync)

        # 统一添加所有智能体节点
        agent_names = []
        for i, agent in enumerate(all_agents):
            # 智能体名称识别逻辑
            if hasattr(agent, 'name'):
                agent_name = agent.name
            elif hasattr(agent, '__class__') and 'dingtalk' in agent.__class__.__name__.lower():
                agent_name = "dingtalk_agent"
            elif hasattr(agent, '__class__') and 'knowledge' in agent.__class__.__name__.lower():
                agent_name = "knowledge_agent"
            elif hasattr(agent, '__class__') and 'text2sql' in agent.__class__.__name__.lower():
                agent_name = "text2sql_agent"
            elif i == 0:
                agent_name = "text2sql_agent"  # 第一个智能体默认为text2sql
            elif 'dingtalk' in str(type(agent)).lower():
                agent_name = "dingtalk_agent"
            elif 'knowledge' in str(type(agent)).lower():
                agent_name = "knowledge_agent"
            else:
                agent_name = f"agent_{i}"

            # 避免重复名称
            if agent_name in agent_names:
                agent_name = f"{agent_name}_{i}"

            agent_names.append(agent_name)
            
            # 创建统一的智能体包装函数
            def create_unified_agent_wrapper(agent_instance, name):
                def agent_wrapper(state: SupervisorState) -> SupervisorState:
                    try:
                        messages = state.get("messages", [])
                        if not messages:
                            return {"next": "FINISH"}

                        # 获取用户输入
                        user_message = None
                        for msg in reversed(messages):
                            if isinstance(msg, HumanMessage):
                                user_message = msg
                                break

                        if not user_message:
                            return {"next": "FINISH"}

                        # 统一的智能体调用逻辑
                        response_content = None

                        # 1. 钉钉智能体处理
                        if name == "dingtalk_agent":
                            try:
                                # 🔧 修复：增强dingtalk_agent错误处理和调试
                                logger.info(f"开始处理钉钉智能体请求: {name}")
                                logger.debug(f"Agent instance type: {type(agent_instance)}")
                                logger.debug(f"Agent instance attributes: {dir(agent_instance) if agent_instance else 'None'}")

                                if not agent_instance:
                                    logger.error("DingTalk agent instance is None")
                                    response_content = "抱歉，钉钉智能体未正确初始化。请联系管理员。"
                                elif not hasattr(agent_instance, 'process_request'):
                                    logger.error(f"DingTalk agent missing process_request method. Type: {type(agent_instance)}")
                                    logger.error(f"Available methods: {[attr for attr in dir(agent_instance) if not attr.startswith('_')]}")
                                    response_content = "抱歉，钉钉智能体接口不完整。请联系管理员。"
                                else:
                                    user_id = state.get("user_id", "default_user")
                                    logger.info(f"调用钉钉智能体: user_id={user_id}, input='{user_message.content}'")

                                    # 🔧 修复：传递重写信息给钉钉智能体
                                    rewrite_info = state.get("rewrite_info", {})
                                    result = agent_instance.process_request(
                                        user_message.content,
                                        user_id,
                                        rewrite_info=rewrite_info
                                    )
                                    logger.debug(f"钉钉智能体返回结果: {result}")

                                    if isinstance(result, dict) and "output" in result:
                                        response_content = result.get("output", "抱歉，钉钉功能暂时不可用。")
                                        if result.get("success", True):
                                            logger.info("钉钉智能体处理成功")
                                        else:
                                            logger.warning(f"钉钉智能体处理失败: {result.get('error', 'Unknown error')}")
                                    else:
                                        logger.error(f"钉钉智能体返回格式错误: {result}")
                                        response_content = "抱歉，钉钉智能体返回了无效的结果。"

                            except Exception as dingtalk_error:
                                logger.error(f"钉钉智能体调用异常: {dingtalk_error}")
                                import traceback
                                logger.error(f"钉钉智能体异常堆栈: {traceback.format_exc()}")
                                response_content = f"抱歉，钉钉功能处理时出现错误。请稍后重试。"

                        # 2. 知识检索智能体处理
                        elif name == "knowledge_agent":
                            try:
                                # 🔧 新增：knowledge_agent错误处理，参考dingtalk_agent模式
                                logger.info(f"开始处理知识检索智能体请求: {name}")
                                logger.debug(f"Agent instance type: {type(agent_instance)}")
                                logger.debug(f"Agent instance attributes: {dir(agent_instance) if agent_instance else 'None'}")

                                if not agent_instance:
                                    logger.error("Knowledge agent instance is None")
                                    response_content = "抱歉，知识检索智能体未正确初始化。请联系管理员。"
                                elif not hasattr(agent_instance, 'process_request'):
                                    logger.error(f"Knowledge agent missing process_request method. Type: {type(agent_instance)}")
                                    logger.error(f"Available methods: {[attr for attr in dir(agent_instance) if not attr.startswith('_')]}")
                                    response_content = "抱歉，知识检索智能体接口不完整。请联系管理员。"
                                else:
                                    user_id = state.get("user_id", "default_user")
                                    session_id = state.get("session_id", "default_session")
                                    logger.info(f"调用知识检索智能体: user_id={user_id}, input='{user_message.content}'")

                                    # 传递查询重写上下文信息
                                    context = {
                                        "rewritten_query": state.get("rewritten_query"),
                                        "rewrite_applied": state.get("rewrite_applied", False),
                                        "reference_type": state.get("reference_type"),
                                        "conversation_history": state.get("conversation_history", [])
                                    }

                                    result = agent_instance.process_request(user_message.content, user_id, session_id, context)
                                    logger.debug(f"知识检索智能体返回结果: {result}")

                                    if isinstance(result, dict) and "output" in result:
                                        response_content = result.get("output", "抱歉，知识检索功能暂时不可用。")
                                        if result.get("success", True):
                                            logger.info("知识检索智能体处理成功")
                                        else:
                                            logger.warning(f"知识检索智能体处理失败: {result.get('error', 'Unknown error')}")
                                    else:
                                        logger.error(f"知识检索智能体返回格式错误: {result}")
                                        response_content = "抱歉，知识检索智能体返回了无效的结果。"

                            except Exception as knowledge_error:
                                logger.error(f"知识检索智能体调用异常: {knowledge_error}")
                                import traceback
                                logger.error(f"知识检索智能体异常堆栈: {traceback.format_exc()}")
                                response_content = f"抱歉，知识检索功能处理时出现错误。请稍后重试。"

                        # 3. Text2SQL智能体处理
                        elif hasattr(agent_instance, 'process_query'):
                            result = agent_instance.process_query(user_message.content)
                            if result and 'messages' in result and result['messages']:
                                last_msg = result['messages'][-1]
                                response_content = last_msg.content if hasattr(last_msg, 'content') else str(last_msg)
                            else:
                                error_msg = result.get('message', '抱歉，我无法处理您的请求。')
                                if result.get('suggestion'):
                                    error_msg += f" {result['suggestion']}"
                                response_content = error_msg

                        # 4. LangGraph智能体处理
                        elif hasattr(agent_instance, 'invoke'):
                            try:
                                input_state = {"messages": [user_message]}
                                result = agent_instance.invoke(input_state)
                                if result and 'messages' in result and result['messages']:
                                    last_msg = result['messages'][-1]
                                    response_content = last_msg.content if hasattr(last_msg, 'content') else str(last_msg)
                                else:
                                    response_content = "抱歉，智能体处理出现问题。"
                            except Exception as e:
                                logger.error(f"LangGraph智能体调用失败: {e}")
                                response_content = "抱歉，处理您的请求时出现错误。请稍后重试。"

                        # 4. 其他类型智能体的通用处理
                        else:
                            response_content = f"抱歉，{name}暂时无法处理您的请求。请稍后重试或联系管理员。"

                        # 创建响应消息
                        response_message = AIMessage(
                            content=response_content,
                            name=name
                        )

                        return {
                            "messages": [response_message],
                            "next": "FINISH"
                        }

                    except Exception as e:
                        logger.error(f"Agent {name} error: {e}")
                        error_message = AIMessage(
                            content=f"抱歉，{name}处理请求时出现了错误。",
                            name=name
                        )
                        return {
                            "messages": [error_message],
                            "next": "FINISH"
                        }

                return agent_wrapper

            # 添加智能体节点
            workflow.add_node(agent_name, create_unified_agent_wrapper(agent, agent_name))

        # 注意：钉钉智能体现在已经统一在上面的循环中处理了
        
        # 设置入口点
        workflow.set_entry_point("supervisor")
        
        # 添加条件边：从 supervisor 到各个智能体
        def route_supervisor(state: SupervisorState) -> str:
            """路由函数"""
            next_agent = state.get("next", "FINISH")
            logger.info(f"Routing to: {next_agent}")
            return next_agent
        
        # 创建智能路由映射
        route_map = {name: name for name in agent_names}
        route_map["FINISH"] = END

        # 确保标准智能体名称的映射
        text2sql_agents = [name for name in agent_names if 'text2sql' in name.lower()]
        dingtalk_agents = [name for name in agent_names if 'dingtalk' in name.lower()]
        knowledge_agents = [name for name in agent_names if 'knowledge' in name.lower()]

        if text2sql_agents and "text2sql_agent" not in route_map:
            route_map["text2sql_agent"] = text2sql_agents[0]
        elif not text2sql_agents and agent_names:
            # 如果没有明确的text2sql智能体，映射到第一个智能体
            route_map["text2sql_agent"] = agent_names[0]

        if dingtalk_agents and "dingtalk_agent" not in route_map:
            route_map["dingtalk_agent"] = dingtalk_agents[0]

        if knowledge_agents and "knowledge_agent" not in route_map:
            route_map["knowledge_agent"] = knowledge_agents[0]

        # 🔧 修复：添加'general'路由映射
        # 当路由到'general'时，supervisor直接处理并结束，不需要额外的智能体
        # 注意：在supervisor节点中，'general'路由会直接返回回复并设置next="FINISH"
        # 这里不需要在route_map中添加'general'，因为它由supervisor内部处理

        logger.info(f"Unified route map: {route_map}")
        logger.info(f"Available agents: {agent_names}")
        
        workflow.add_conditional_edges(
            "supervisor",
            route_supervisor,
            route_map
        )
        
        # 从智能体回到结束
        for agent_name in agent_names:
            workflow.add_edge(agent_name, END)
        
        logger.info("Supervisor workflow created successfully")
        return workflow
        
    except Exception as e:
        logger.error(f"Failed to create supervisor: {e}")
        raise

def create_memory_enhanced_supervisor(agents: List[Any], model: Any, prompt: str, memory_manager=None) -> StateGraph:
    """
    创建支持记忆增强的 Supervisor 工作流
    
    Args:
        agents: 智能体列表
        model: 语言模型
        prompt: Supervisor 提示词
        memory_manager: 记忆管理器
        
    Returns:
        编译后的工作流
    """
    try:
        logger.info("Creating memory-enhanced supervisor")
        
        # 创建基础工作流
        workflow = create_supervisor(agents, model, prompt)
        
        # 如果有记忆管理器，添加记忆增强节点
        if memory_manager:
            # 添加记忆上下文节点
            def memory_context_node(state: SupervisorState) -> SupervisorState:
                """记忆上下文节点"""
                try:
                    messages = state.get("messages", [])
                    session_id = state.get("session_id", "default")
                    
                    if messages and memory_manager:
                        # 获取用户输入
                        user_message = None
                        for msg in reversed(messages):
                            if isinstance(msg, HumanMessage):
                                user_message = msg
                                break
                        
                        if user_message:
                            # 获取相关记忆
                            try:
                                memory_history = memory_manager.get_memory(session_id)
                                if memory_history and hasattr(memory_history, 'messages') and memory_history.messages:
                                    # 添加记忆上下文
                                    context_message = AIMessage(
                                        content="[记忆上下文] 我记得我们之前的对话。",
                                        name="memory_context"
                                    )
                                    return {"messages": [context_message]}
                            except Exception as e:
                                logger.warning(f"Memory retrieval failed: {e}")
                    
                    return {"messages": []}
                    
                except Exception as e:
                    logger.error(f"Memory context node error: {e}")
                    return {"messages": []}
            
            # 重新构建工作流以包含记忆节点
            # 这里简化处理，在实际使用中会通过状态传递记忆信息
            
        logger.info("Memory-enhanced supervisor created successfully")
        return workflow
        
    except Exception as e:
        logger.error(f"Failed to create memory-enhanced supervisor: {e}")
        return create_supervisor(agents, model, prompt)  # 降级到基础版本

# 便捷函数
def compile_supervisor_with_memory(workflow: StateGraph, checkpointer: MemorySaver = None):
    """
    编译带记忆的 Supervisor 工作流
    
    Args:
        workflow: 工作流图
        checkpointer: 记忆检查点
        
    Returns:
        编译后的应用
    """
    try:
        if checkpointer is None:
            checkpointer = MemorySaver()
        
        app = workflow.compile(checkpointer=checkpointer)
        logger.info("Supervisor compiled with memory support")
        return app
        
    except Exception as e:
        logger.error(f"Failed to compile supervisor with memory: {e}")
        # 降级到无记忆版本
        return workflow.compile()

# 向后兼容的别名
def get_supervisor_workflow():
    """向后兼容的工作流获取函数"""
    # 这个函数用于测试，返回一个模拟的工作流对象
    class MockWorkflow:
        def __init__(self):
            self.agents = {"text2sql_agent": None, "dingtalk_agent": None}
            self.app = None
    
    return MockWorkflow()
